﻿@page "/file"
@inject IJSRuntime JavaScript;
@rendermode InteractiveServer

@using System.Security.Cryptography
@using System.Text
@using System.IO.Compression
@using System.Xml.Linq

<h3>文件中心</h3>

<label>@msg</label><br />
<input @bind="fileUrl" placeholder="文件路径" />
<button @onclick="DownloadFile">下载文件</button>



@code {
    private string fileUrl = string.Empty;
    private string msg = string.Empty;
    private string reimNo = "1";
    private string completeUrl = string.Empty;


    private async Task ShowDialog()
    {
        var options = new
        {
            title = "Do you want to save the changes?",
            showDenyButton = true,
            showCancelButton = true,
            confirmButtonText = "Save",
            denyButtonText = "Don't save"
        };
        var result = await JavaScript.InvokeAsync<FireResponse>("Swal.fire", options);
        if (result.IsConfirmed)
        {
            await JavaScript.InvokeVoidAsync("Swal.fire", new
            {

                PageTitle = "deleted",
                text = "Your file has been deleted",
                icon = "success"
            });
        }
    }

    private async Task DownloadFile()
    {
        try
        {
            msg = "开始生成url";
            // 下载文件
            // 1. 提取 fileId (去掉第一个 '/' 之前的部分)
            string fileId = fileUrl.Substring(fileUrl.IndexOf("/") + 1);

            // 2. 获取当前时间戳 (秒)
            int ts = (int)(DateTimeOffset.UtcNow.ToUnixTimeSeconds());

            // 3. 生成 token
            string token = GetToken(fileId, ts, "SFqdFASTDFS#@!$%^");

            // 4. 构造带参数的 URL
            string queryString = $"token={token}&ts={ts}";
            string fullFileUrl = $"{fileUrl}?{queryString}";

            // 5. 构造完整的下载 URL
            // 注意：原始 Java 代码中 URL 后面有空格，这里已修正
            completeUrl = $"https://image.gwhome.com.cn/{fullFileUrl}";

            Console.WriteLine($"下载地址: {completeUrl}");


            byte[] bytes = await HttpUtil.DownloadBytesAsync(completeUrl);

            using (MemoryStream ms = new MemoryStream(bytes))
            {
                // 这里可以对字节数组进行处理，例如解压缩等
                using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Read))
                {
                    // 读取 ZIP 文件的注释
                    string comment = archive.Comment;
                    foreach (ZipArchiveEntry entry in archive.Entries)
                    {
                        Console.WriteLine($"文件名: {entry.FullName}, 大小: {entry.Length} 字节");
                        //读取content.xml文件中的  ReimbursementFormNo 这个节点的值
                        if (entry.FullName.EndsWith("content.xml", StringComparison.OrdinalIgnoreCase))
                        {
                            using (StreamReader reader = new StreamReader(entry.Open()))
                            {
                                string content = reader.ReadToEnd();
                                // 这里可以解析 XML 内容，提取 ReimbursementFormNo 节点的值

                                try
                                {
                                    var xdoc = XDocument.Parse(content);
                                    // 假设节点路径为 <ReimbursementFormNo>xxx</ReimbursementFormNo>
                                    var node = xdoc.Descendants("ReimbursementFormNo").FirstOrDefault();
                                    if (node != null)
                                    {
                                        reimNo = node.Value;
                                        Console.WriteLine($"ReimbursementFormNo: {reimNo}");
                                    }
                                    else
                                    {
                                        Console.WriteLine("未找到 ReimbursementFormNo 节点");
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine($"解析 XML 失败: {ex.Message}");
                                }
                            }
                        }
                    }
                    Console.WriteLine(comment);
                }
            }
            // string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            // string localFilePath = Path.Combine(desktopPath, "evd1", $"{reimNo}.evd");
            // FileInfo file = new FileInfo(localFilePath);
            await JavaScript.InvokeVoidAsync("downloadFileFromBytes", bytes, $"{reimNo}.evd", "application/zip");
            msg = "下载成功";
            // Base64Utils.CopyByte2File(bytes, file);
        }
        catch (Exception ex)
        {

            msg = $"下载文件失败: {ex.Message}";
        }

    }


    public class FireResponse
    {
        public bool IsConfirmed { get; set; }
    }

    /// <summary>
    /// 根据文件ID、时间戳和密钥生成 FastDFS 下载 token。
    /// </summary>
    /// <param name="remote_filename">远程文件名 (fileId)</param>
    /// <param name="ts">时间戳 (Unix 时间戳，单位：秒)</param>
    /// <param name="secret_key">密钥</param>
    /// <returns>生成的 MD5 token 字符串</returns>
    public static string GetToken(string remote_filename, int ts, string secret_key)
    {
        // 将字符串转换为 UTF-8 字节数组
        byte[] bsFilename = Encoding.UTF8.GetBytes(remote_filename);
        byte[] bsKey = Encoding.UTF8.GetBytes(secret_key);
        byte[] bsTimestamp = Encoding.UTF8.GetBytes(ts.ToString());

        // 创建一个新数组，长度为三个字节数组的总和
        byte[] buff = new byte[bsFilename.Length + bsKey.Length + bsTimestamp.Length];

        // 使用 Buffer.BlockCopy 或 Array.Copy 将三个字节数组拼接起来
        // Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length)
        Array.Copy(bsFilename, 0, buff, 0, bsFilename.Length);
        Array.Copy(bsKey, 0, buff, bsFilename.Length, bsKey.Length);
        Array.Copy(bsTimestamp, 0, buff, bsFilename.Length + bsKey.Length, bsTimestamp.Length);

        // 计算拼接后字节数组的 MD5 值，并返回十六进制字符串
        return Md5(buff);
    }

    /// <summary>
    /// 计算字节数组的 MD5 哈希值，并返回其小写十六进制字符串表示。
    /// </summary>
    /// <param name="source">要计算哈希值的字节数组</param>
    /// <returns>32位小写十六进制字符串</returns>
    public static string Md5(byte[] source)
    {
        // 创建 MD5 哈希算法实例
        using (MD5 md5 = MD5.Create())
        {
            // 计算哈希值
            byte[] hashBytes = md5.ComputeHash(source);

            // 将哈希字节数组转换为十六进制字符串
            // 使用 StringBuilder 高效地构建字符串
            StringBuilder sb = new StringBuilder(32); // MD5 固定32位
            foreach (byte b in hashBytes)
            {
                sb.Append(b.ToString("x2")); // "x2" 格式化为两位小写十六进制数
            }
            return sb.ToString();
        }
    }



    public static class HttpUtil
    {
        // 使用 static HttpClient 实例以获得最佳性能
        private static readonly HttpClient httpClient = new HttpClient();

        public static async Task<byte[]> DownloadBytesAsync(string url)
        {
            try
            {
                // 发送 GET 请求并获取响应流
                HttpResponseMessage response = await httpClient.GetAsync(url);
                response.EnsureSuccessStatusCode(); // 确保请求成功 (状态码 2xx)
                return await response.Content.ReadAsByteArrayAsync();
            }
            catch (HttpRequestException e)
            {
                // 处理网络请求异常
                Console.WriteLine($"请求失败: {e.Message}");
                throw;
            }
        }
    }

    // 一个简单的 Base64 工具类（尽管这里不需要Base64编码，但用于写文件）
    public static class Base64Utils
    {
        public static void CopyByte2File(byte[] bytes, FileInfo file)
        {
            try
            {
                // 确保目标目录存在
                file.Directory?.Create();

                // 将字节数组写入文件
                File.WriteAllBytes(file.FullName, bytes);
                Console.WriteLine($"文件已成功保存到: {file.FullName}");
            }
            catch (IOException e)
            {
                // 处理文件写入异常
                Console.WriteLine($"写入文件失败: {e.Message}");
                throw;
            }
        }
    }
}




